<?php
namespace App\Admin\Controllers\Shipping;

use App\Admin\Actions\Shipping\ImportRemarks;
use App\Admin\Actions\Shipping\OneKeyLock;
use App\Admin\Actions\Shipping\SyncTotal;
use App\Admin\Actions\Shipping\SyncTotalSku;
use App\Admin\Ajax\Shipping\TotalAjax;
use App\Admin\Extensions\Grid\Tool\Export;
use App\Models\Inventory\Timely;
use App\Models\Product\ProductClassify;
use App\Models\Product\ProductSku;
use App\Models\Shipping\SSkuApply;
use App\Models\Shipping\SSkuTotal;
use App\Models\Shipping\SSkuTotalApply;
use App\Util\RExcel;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Facades\Admin;
use Encore\Admin\Grid;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Facades\Request;

class TotalController extends AdminController{

    protected $title = '提货产品汇总';

    protected function grid()
    {
        $shippingDate = SSkuApply::initShippingDate();
        $firstKey = array_key_first($shippingDate);
        $lastKey = array_key_last($shippingDate);
        $grid = new Grid(new SSkuTotal());
        $grid->model()->whereHas('sku',function ($query){
            $query->where('status',1); //在售产品
        });
        $grid->model()->collection(function (Collection $collection) use ($shippingDate,$firstKey,$lastKey){
            foreach($collection as $index => $item) {
                $instant = Timely::getInstant($item->psku_id); //sku国内在库（实时库存）
                $transit = Timely::getTransit($item->psku_id); //sku国内在途（实时库存）

                $mPSkuId = $item->sku->m_psku_id ?? 0; //产品主skuId
                if($mPSkuId){
                    if($mPSkuId != $item->psku_id){
                        $mPSkuCode = ProductSku::getValueById($mPSkuId,'psku_code');
                        $item->m_psku_code = $mPSkuCode ?: ''; //产品主sku
                        $mInstant = Timely::getInstant($mPSkuId); //主sku国内在库
                        $mTransit = Timely::getTransit($mPSkuId); //主sku国内在途
                    }else{
                        $item->m_psku_code = $item->sku->psku_code ?? '';
                        $mInstant = $instant;
                        $mTransit = $transit;
                    }
                }else{
                    $item->m_psku_code = '';
                    $mInstant = 0;
                    $mTransit = 0;
                }
                $item->instant = $instant;
                $item->transit = $transit;
                $item->m_instant = $mInstant; //主sku国内在库
                $item->m_transit = $mTransit; //主sku国内在途
                $_shippingDate = array_keys($shippingDate); //提货日期
                $item->storage_num_0 = SSkuTotal::getStorageNum($_shippingDate[0],$_shippingDate[1],$mPSkuId); //主sku当期到货数量 (主sku国内收货入库数量)

                $applyNum = SSkuTotalApply::getApplyNum($item->psku_id,$firstKey,$lastKey); //当期sku提货审核数量
                foreach ($shippingDate as $date => $label){
                    $item->{'apply_num'.$label} = array_key_exists($date,$applyNum) ? $applyNum[$date] : 0;
                }

                //当期结余 = 主sku当期到货数量 - 当期提货审核数量
                $item->differ_num_0 = $item->storage_num_0 - (array_key_exists($_shippingDate[0],$applyNum) ? $applyNum[$_shippingDate[0]] : 0);

                //实际结余 = 当期结余 + 往期结余
                $item->r_differ = $item->differ_num_0 - $item->t_differ;
            }
            return $collection;
        });
        $grid->column('sku.psku_cn','产品名称');
        $grid->column('sku.psku_code','SKU');
        $grid->column('m_psku_code','主SKU')->help('主产品');
        $grid->column('skuClassify.title','品类');
        $grid->column('skuClassify.season','季节性')->using(ProductClassify::$_season);
        $grid->column('instant','在库');
        $grid->column('transit','在途');
        $grid->column('m_instant','主sku在库1')->help('主产品在库');
        $grid->column('m_transit','主sku在途1')->help('主产品在途');
        foreach ($shippingDate as $date => $label){
            if($firstKey == $date){
                $grid->column('apply_num'.$label,$label.'需求')->style('background-color: #00c0ef;');
            }else{
                $grid->column('apply_num'.$label,$label.'需求');
            }
        }
        $grid->column('storage_num_0','当期到货')->help('当前周期主产品到货总数');
        $grid->column('differ_num_0','当期结余')->help('当前周期主产品到货总数 - 当前周期需求数');
        $grid->column('t_differ','往期结余')->help('当前周期之前的总结余');
        $grid->column('r_differ','实际结余')->help('当期结余 + 往期结余');
        $grid->column('remarks','备注');
        $grid->column('is_lock','锁状态')->display(function ($value){
            return SSkuTotal::$_isLock[$value];
        });
        if(Admin::user()->can('shipping.total.edit')){
            $grid->tools(function (Grid\Tools $tools) {
                $tools->append(new ImportRemarks()); //导入备注
                $tools->append(new OneKeyLock()); //一键锁定
                $tools->append(new SyncTotal()); //一键同步汇总
                $tools->append(new SyncTotalSku()); //单个sku汇总
            });
        }
        $grid->disableExport();
        $grid->tools(function (Grid\Tools $tools){
            $tools->append(new Export('shipping/total-download'));
        });
        $grid->disableActions();
        $grid->disableCreateButton();
        $grid->disableRowSelector();
        $grid->paginate(10);
        $grid->fixColumns(3);
        $grid->filter(function($filter){
            $filter->column(1/3, function ($filter) {
                $filter->where(function ($query) {
                    $query->whereHas('sku', function ($query) {
                        $query->where('psku_code', 'like', "%{$this->input}%")
                            ->orWhere('psku_cn', 'like', "%{$this->input}%");
                    });
                }, 'SKU','sku8')->placeholder('模糊查询SKU，名称');
            });
            $filter->column(1/3, function ($filter){
                $filter->equal('sku.classify_id', '品类')->select(ProductClassify::options());
            });
        });

        return $grid;
    }

    public function ajax(){
        $action = request('action');
        $param = request('param');
        $ajax = new TotalAjax();
        return $param ? call_user_func([$ajax,$action],$param) : call_user_func([$ajax,$action]);
    }

    public function download(){
        $request = Request::input();
        $query = $this->_initQuery($request);
        $this->_exeDownload($query);
    }

    private function _initQuery($filters){
        $query = SSkuTotal::query()
            ->whereHas('sku',function ($query){
                $query->where('status',1); //在售产品
            })
            ->orderBy('id', 'DESC');
        foreach ($filters as $key => $_filter){
            if($key == 'sku8'){
                $query->whereHas('sku', function ($query) use($_filter){
                    $query->where('psku_code', 'like', "%{$_filter}%")
                        ->orWhere('psku_cn', 'like', "%{$_filter}%");
                });
            }
            if($key == 'sku'){
                $query->whereHas('sku', function ($query) use($_filter){
                    $query->where('classify_id', $_filter['classify_id']);
                });
            }
        }
        return $query;
    }

    private function _exeDownload($query){
        $shippingDate = SSkuApply::initShippingDate();
        $head1 = ['产品名称','SKU','主SKU','品类','季节性','在库','在途', '主sku在库1','主sku在途1',];
        $head2 = [];
        foreach ($shippingDate as $label){
            $head2[] = $label.'需求';
        }
        $head3 = ['当期到货','当期结余','往期结余','实际结余','备注','状态'];
        $head = array_merge($head1,$head2,$head3);
        RExcel::exportCsv('提货产品汇总',function () use ($head, $query,$shippingDate) {
            $fp = fopen('php://output', 'w');
            fwrite($fp, chr(0xEF).chr(0xBB).chr(0xBF));
            fputcsv($fp, $head);
            $query->chunk(1000, function ($re) use ($fp,$shippingDate){
                $data = self::_getDownloadData($re,$shippingDate);
                foreach ($data as $item) {
                    fputcsv($fp, $item);
                }
            });
        });
    }

    private static function _getDownloadData($res,$shippingDate)
    {
        foreach ($res as $model){
            $mPSkuId = $model->sku->m_psku_id ?? 0;
            $instant = Timely::getInstant($model->psku_id);
            $transit = Timely::getTransit($model->psku_id);
            if($mPSkuId){
                if($mPSkuId != $model->psku_id){
                    $mPSkuCode = ProductSku::getValueById($mPSkuId,'psku_code');
                    $mInstant = Timely::getInstant($mPSkuId);
                    $mTransit = Timely::getTransit($mPSkuId);
                }else{
                    $mPSkuCode = $model->sku->psku_code ?? '';
                    $mInstant = $instant;
                    $mTransit = $transit;
                }
            }else{
                $mPSkuCode = '';
                $mInstant = 0;
                $mTransit = 0;
            }
            $data1 = [
                $model->sku->psku_cn ?? '',
                $model->sku->psku_code ?? '',
                $mPSkuCode ?: '',
                $model->skuClassify->title ?? '',
                ProductClassify::$_season[$model->skuClassify->season ?? 3],
                $instant,
                $transit,
                $mInstant,
                $mTransit];
            $data2 = [];
            $_shippingDate = array_keys($shippingDate);
            //当期sku提货审核数量
            $applyNum = SSkuTotalApply::getApplyNum($model->psku_id,array_key_first($shippingDate),array_key_last($shippingDate));
            foreach ($shippingDate as $date => $label){
                $data2[] = array_key_exists($date,$applyNum) ? $applyNum[$date] : 0;
            }
            //主sku当期到货数量
            $storage_num_0 = SSkuTotal::getStorageNum($_shippingDate[0],$_shippingDate[1],$mPSkuId);
            //当期结余
            $differ_num_0 = $storage_num_0 - (array_key_exists($_shippingDate[0],$applyNum) ? $applyNum[$_shippingDate[0]] : 0);
            //实际结余
            $r_differ = $differ_num_0 - $model->t_differ;
            $data3 = [
                $storage_num_0,
                $differ_num_0,
                $model->t_differ, //往期结余
                $r_differ,
                $model->remarks,
                SSkuTotal::$_isLock[$model->is_lock],
            ];
            $temp = array_merge($data1,$data2,$data3);
            yield $temp;
        }
    }
}
